package org.zjx.operation.impl;

import com.sun.jna.platform.win32.BaseTSD;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;
import lombok.Setter;
import org.zjx.core.IWindow;
import org.zjx.util.ImageUtil;
import org.zjx.util.WindowCaptureUtil;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.List;

@Setter
public class BaseGameOperator extends RobotOperator {

    @Override
    public IWindow getWindow() {
        return super.getWindow();
    }

    @Override
    public void setWindow(IWindow window) {
        this.window = window;
    }

    @Override
    public BufferedImage screenshot() {
        BufferedImage screenshot = WindowCaptureUtil.getInstance().captureWindow(window.getHwnd());
        screenshot = ImageUtil.cutImage(screenshot,window.getTrueBounds());
        return screenshot;
    }

    @Override
    public BufferedImage screenshot(Rectangle region) {
        BufferedImage screenshot = screenshot();
        return ImageUtil.cutImage(screenshot,region);
    }

    @Override
    public void move(int x, int y) {
        mousePosition = new Point(x, y);
        User32.INSTANCE.SendMessage(window.getHwnd(), 0x200, new WinDef.WPARAM(0),
                new WinDef.LPARAM(((long) y << 16) | (x & 0xFFFF)));
    }

    @Override
    public void click(int x, int y) {
        gameMove(x, y);
        delay(30);
        click(1);
    }

    @Override
    public void click(int button) {
        pressMouse(button);
        delay(10);
        releaseMouse(button);
    }

    @Override
    public void pressMouse(int button) {
        User32.INSTANCE.SendMessage(window.getHwnd(), button == 1?0x0201:0x0204, new WinDef.WPARAM(0), null);

    }

    @Override
    public void releaseMouse(int button) {
        User32.INSTANCE.SendMessage(window.getHwnd(),  button == 1?0x0202:0x0205, new WinDef.WPARAM(0), null);
    }

    @Override
    public Point getMousePosition() {
        return mousePosition;
    }

    @Override
    public void drag(int fromX, int fromY, int toX, int toY) {
        move(fromX, fromY);
        delay(30);
        pressMouse(1);
        delay(30);
        move(toX, toY);
        delay(30);
        releaseMouse(1);
    }

    @Override
    public void press(int keyCode) {
        super.press(keyCode);
    }

    @Override
    public void pressKey(int keyCode) {
        super.pressKey(keyCode);
    }

    @Override
    public void releaseKey(int keyCode) {
        super.releaseKey(keyCode);
    }

    @Override
    public void type(String text) {
        if (text == null || text.isEmpty()) return;
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            sendChar(c);
            delay(100);
        }
    }

    @Override
    public void hotkey(int... keyCodes) {
        super.hotkey(keyCodes);
    }

    @Override
    public Point findImage(BufferedImage template) {
        List<Point> points = findAllImages(template);
        return points.isEmpty() ? null : points.get(0);
    }

    @Override
    public List<Point> findAllImages(BufferedImage template) {
        BufferedImage screenshot = screenshot();
        return ImageUtil.matchTemplate(screenshot, template);
    }

    @Override
    public boolean findColor(Rectangle region, Color targetColor) {
        return findColor(region, Collections.singletonList(targetColor));
    }

    @Override
    public boolean findColor(Rectangle region, List<Color> targetColors) {
        BufferedImage screenshot = screenshot();
        BufferedImage bufferedImage = ImageUtil.cutImage(screenshot,region);
        return ImageUtil.haveColor(bufferedImage, targetColors);
    }

    @Override
    public Color getColor(int x, int y) {
        BufferedImage screenshot = screenshot();
        return new Color(screenshot.getRGB(x,y));
    }

    @Override
    public void delay(long milliseconds) {
        super.delay(milliseconds);
    }

    @Override
    public Robot getRobot() {
        return super.getRobot();
    }


    private static final WinUser.INPUT input = new WinUser.INPUT();

    private void sendChar(char ch) {
        input.type = new WinDef.DWORD(1L);
        input.input.setType("ki");
        input.input.ki.wScan = new WinDef.WORD(0L);
        input.input.ki.time = new WinDef.DWORD(0L);
        input.input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0L);

        // 对于ASCII字符，使用常规方式
        boolean needsShift = false;
        int virtualKey = 0;

        // 处理 Unicode 字符
        if (ch > 255) {
            // 对于非ASCII字符，使用虚拟键码0（VK_PACKET）
            input.input.ki.wVk = new WinDef.WORD(0);
            input.input.ki.wScan = new WinDef.WORD(ch);
            input.input.ki.dwFlags = new WinDef.DWORD(0x0004); // KEYEVENTF_UNICODE
        } else {
            // 处理特殊字符
            switch (ch) {
                case '~':
                    needsShift = true;
                    virtualKey = 192;
                    break; // `键
                case '!':
                    needsShift = true;
                    virtualKey = 49;
                    break;  // 1键
                case '@':
                    needsShift = true;
                    virtualKey = 50;
                    break;  // 2键
                case '#':
                    needsShift = true;
                    virtualKey = 51;
                    break;  // 3键
                case '$':
                    needsShift = true;
                    virtualKey = 52;
                    break;  // 4键
                case '%':
                    needsShift = true;
                    virtualKey = 53;
                    break;  // 5键
                case '^':
                    needsShift = true;
                    virtualKey = 54;
                    break;  // 6键
                case '&':
                    needsShift = true;
                    virtualKey = 55;
                    break;  // 7键
                case '*':
                    needsShift = true;
                    virtualKey = 56;
                    break;  // 8键
                case '(':
                    needsShift = true;
                    virtualKey = 57;
                    break;  // 9键
                case ')':
                    needsShift = true;
                    virtualKey = 48;
                    break;  // 0键
                case '_':
                    needsShift = true;
                    virtualKey = 189;
                    break; // -键
                case '+':
                    needsShift = true;
                    virtualKey = 187;
                    break; // =键
                case '{':
                    needsShift = true;
                    virtualKey = 219;
                    break; // [键
                case '}':
                    needsShift = true;
                    virtualKey = 221;
                    break; // ]键
                case '|':
                    needsShift = true;
                    virtualKey = 220;
                    break; // \键
                case ':':
                    needsShift = true;
                    virtualKey = 186;
                    break; // ;键
                case '"':
                    needsShift = true;
                    virtualKey = 222;
                    break; // '键
                case '<':
                    needsShift = true;
                    virtualKey = 188;
                    break; // ,键
                case '>':
                    needsShift = true;
                    virtualKey = 190;
                    break; // .键
                case '?':
                    needsShift = true;
                    virtualKey = 191;
                    break; // /键
                case ' ':
                    virtualKey = 32;
                    break; // 空格键
                case '\t':
                    virtualKey = 9;
                    break; // 制表符
                case '\n':
                    virtualKey = 13;
                    break; // 回车键
                case '.':
                    virtualKey = 190;
                    break; // 点号
                default:
                    if (Character.isUpperCase(ch)) {
                        needsShift = true;
                        virtualKey = Character.toUpperCase(ch);
                    } else {
                        virtualKey = Character.toUpperCase(ch);
                    }
            }

            if (needsShift) {
                pressKey(16, true); // 按下Shift
                delay(30);
            }

            input.input.ki.wVk = new WinDef.WORD((long) virtualKey);
            input.input.ki.dwFlags = new WinDef.DWORD(0L);
        }

        User32.INSTANCE.SendInput(new WinDef.DWORD(1L), (WinUser.INPUT[]) input.toArray(1), input.size());
        input.input.ki.dwFlags = new WinDef.DWORD(2L); // KEYEVENTF_KEYUP
        User32.INSTANCE.SendInput(new WinDef.DWORD(1L), (WinUser.INPUT[]) input.toArray(1), input.size());

        if (needsShift) {
            pressKey(16, false); // 释放Shift
            delay(30);
        }
    }

    // 模拟按下或释放 Shift 键
    private static void pressKey(int keyCode, boolean press) {
        input.input.ki.wVk = new WinDef.WORD(keyCode);
        input.input.ki.dwFlags = press ? new WinDef.DWORD(0) : new WinDef.DWORD(2); // 按下或释放
        User32.INSTANCE.SendInput(new WinDef.DWORD(1), (WinUser.INPUT[]) input.toArray(1), input.size());
    }
}
